package web.util;

import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

/**
 * LDAP ad域认证
 * 
 * @author Administrator
 */
@Component("ldapUserUtil")
public class LdapUserUtil {

	private String hostName; // ldap服务器名字
	private int hostPort = 0; // ldap服务器端口
	private String mailPostfix; // 信箱后缀
	private String userPrefix;
	private String ldapCtxFactory; // 初始化工厂
	private String rootDN; // ldap服务器dn
	private String searchRegion; // 搜索范围
	private String admin;
	private String adminPassword;

	public LdapUserUtil() throws Exception {
		// 读取配置信息
		InputStream inputStream = this.getClass().getClassLoader()
				.getResourceAsStream("config.properties");
		Properties property = new Properties();
		if (inputStream == null) {
			return;
		}
		try {
			// 获取ldap服务器相关信息
			property.load(inputStream);
			hostName = property.get("hostName").toString();
			hostPort = Integer.parseInt(property.get("hostPort").toString());
			mailPostfix = property.get("mailPostfix").toString();
			userPrefix = property.get("userPrefix").toString();
			ldapCtxFactory = property.get("ldapCtxFactory").toString();
			rootDN = property.get("rootDN").toString();
			searchRegion = property.get("searchRegion").toString();
			admin = property.get("admin").toString();
			adminPassword = property.get("password").toString();
		} catch (IOException e1) {
			throw new Exception("ldapConfigLoadError");
		} catch (NumberFormatException e) {
			throw new Exception("ldapPortLoadError");
		}
	}

	// 条目的属性集合
	// objectCategory
	// whenCreated
	// badPwdCount
	// mDBUseDefaults
	// codePage
	// mail
	// objectGUID
	// msExchUserAccountControl
	// msExchMailboxSecurityDescriptor
	// msExchALObjectVersion
	// memberOf
	// msExchMailboxGuid
	// msRTCSIP-OptionFlags
	// instanceType
	// msExchPoliciesIncluded
	// objectSid
	// badPasswordTime
	// proxyAddresses
	// dSCorePropagationData
	// msRTCSIP-PrimaryUserAddress
	// objectClass
	// company
	// name
	// sn
	// userAccountControl
	// primaryGroupID
	// msRTCSIP-FederationEnabled
	// lastLogon
	// accountExpires
	// uSNChanged
	// msRTCSIP-UserEnabled
	// cn
	// textEncodedORAddress
	// msRTCSIP-PrimaryHomeServer
	// logonCount
	// msExchHomeServerName
	// homeMTA
	// sAMAccountType
	// legacyExchangeDN
	// givenName
	// uSNCreated
	// displayName
	// userPrincipalName
	// pwdLastSet
	// whenChanged
	// lastLogonTimestamp
	// department
	// countryCode
	// mailNickname
	// distinguishedName
	// msRTCSIP-InternetAccessEnabled
	// homeMDB
	// showInAddressBook
	// sAMAccountName

	public DirContext createDirContext(String loginName, String password)
			throws Exception {
		if (hostPort == 0) {
			hostPort = 389;
		}
		// 构造需要的信息
		String hostURL = "ldap://" + hostName + ":" + String.valueOf(hostPort);
		// 配置验证属性
		Properties props = new Properties();
		props.put(Context.INITIAL_CONTEXT_FACTORY, ldapCtxFactory); // LDAP工厂类
		props.put(Context.SECURITY_AUTHENTICATION, "simple"); // LDAP访问安全级别
		props.put(Context.SECURITY_PRINCIPAL, userPrefix + loginName); // AD
																		// User
																		// ;注意用户名的写法：domain\User
																		// 或
																		// User@huarui.com
		props.put(Context.SECURITY_CREDENTIALS, password); // AD Password
		props.put(Context.PROVIDER_URL, hostURL);
		return new InitialDirContext(props);
	}

	@SuppressWarnings("finally")
	public LdapUser searchUser(String username) {
		try {
			// 进行用户域验证
			DirContext context = createDirContext(admin, adminPassword);
			// 条件查询
			SearchControls constraints = new SearchControls();
			constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
			String filter = "SAMAccountName=" + username;
			// 执行查询操作
			NamingEnumeration en = context.search(searchRegion, filter,
					constraints);
			LdapUser user = null;
			if (en == null) {
				return null;
			} else {
				while (en.hasMoreElements()) {
					Object obj = en.nextElement();
					if (obj instanceof SearchResult) {
						SearchResult sr = (SearchResult) obj;
						user = new LdapUser();
						user.setYhm((String) sr.getAttributes()
								.get("SAMAccountName").get());
						user.setYhmqc((String) sr.getAttributes().get("cn")
								.get());
						user.setDisginguishedname((String) sr.getAttributes()
								.get("distinguishedName").get());
						user.setEmail((String) sr.getAttributes()
								.get("userPrincipalName").get());
						user.setSzdw((String) sr.getAttributes()
								.get("department").get());
					}
				}
				context.close();
			}
			if (context != null) {
				context.close();
			}
			return user;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@SuppressWarnings("finally")
	public List<LdapUser> searchUsers(String condition, String region)
			throws Exception {
		try {
			// 进行用户域验证
			DirContext context = createDirContext(admin, adminPassword);
			// 条件查询
			SearchControls constraints = new SearchControls();
			constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
			String filter = "SAMAccountName=" + condition;
			String r = searchRegion;
			if (null != region) {
				r = region;
			}
			// 执行查询操作
			NamingEnumeration en = context.search(r, filter, constraints);
			List<LdapUser> users = null;
			if (en == null) {
				return null;
			} else {
				users = new ArrayList<LdapUser>();
				while (en.hasMoreElements()) {
					Object obj = en.nextElement();
					if (obj instanceof SearchResult) {
						SearchResult sr = (SearchResult) obj;
						LdapUser lu = new LdapUser();
						lu.setYhm((String) sr.getAttributes()
								.get("SAMAccountName").get());
						lu.setYhmqc((String) sr.getAttributes().get("cn").get());
						lu.setDisginguishedname((String) sr.getAttributes()
								.get("distinguishedName").get());
						lu.setEmail((String) sr.getAttributes()
								.get("userPrincipalName").get());
						lu.setSzdw((String) sr.getAttributes()
								.get("department").get());
						users.add(lu);
					}
				}
				context.close();
			}
			if (context != null) {
				context.close();
			}
			return users;
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception(e);
		}
	}

	/**
	 * 通过ldap验证用户信息
	 * 
	 * @param loginName
	 *            用户名
	 * @param password
	 *            密码
	 * @return 验证是否通过
	 * @throws Exception
	 */
	@SuppressWarnings("finally")
	public String authentica(String loginName, String password) {
		String result = null;
		if (hostName == null) {
			return null;
		}

		try {
			// 进行用户域验证
			DirContext context = createDirContext(loginName, password);

			// 条件查询
			SearchControls constraints = new SearchControls();
			constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
			String filter = "SAMAccountName=" + loginName;

			// 执行查询操作
			NamingEnumeration en = context.search(searchRegion, filter,
					constraints);
			if (en == null) {
				System.out.println("There have no value");
			} else {
				while (en.hasMoreElements()) {
					Object obj = en.nextElement();
					if (obj instanceof SearchResult) {
						SearchResult sr = (SearchResult) obj;
						// 必须在判断用户密码正确前，对帐号激活属性进行判断；否则将出现异常 66048
						int control = Integer.parseInt(sr.getAttributes()
								.get("userAccountControl").get().toString());
						if ((control & 2) > 0) {
							System.out.println(sr.getAttributes().get(
									"SAMAccountName")
									+ "  ldap 认证失败,帐号未激活"
									+ sr.getAttributes().get("cn"));
							result = null;
						} else {
							System.out.println(sr.getAttributes().get(
									"SAMAccountName")
									+ "  ldap 认证成功"
									+ sr.getAttributes().get("cn"));
							result = (String) sr.getAttributes().get("cn")
									.get();
						}
					}
				}
			}

			if (context != null) {
				context.close();
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			result = null;
		} finally {
			return result;
		}
	}

	public String getHostName() {
		return hostName;
	}

	public void setHostName(String hostName) {
		this.hostName = hostName;
	}

	public int getHostPort() {
		return hostPort;
	}

	public void setHostPort(int hostPort) {
		this.hostPort = hostPort;
	}

	public String getMailPostfix() {
		return mailPostfix;
	}

	public void setMailPostfix(String mailPostfix) {
		this.mailPostfix = mailPostfix;
	}

	public String getRootDN() {
		return rootDN;
	}

	public void setRootDN(String rootDN) {
		this.rootDN = rootDN;
	}

	public String getLdapCtxFactory() {
		return ldapCtxFactory;
	}

	public void setLdapCtxFactory(String ldapCtxFactory) {
		this.ldapCtxFactory = ldapCtxFactory;
	}

	public String getUserPrefix() {
		return userPrefix;
	}

	public void setUserPrefix(String userPrefix) {
		this.userPrefix = userPrefix;
	}
	//
	// public static void main(String args[]) throws Exception {
	// LdapUserUtil ldapUserUtil = new LdapUserUtil();
	// try {
	// JSONArray js = JSONArray.fromObject(ldapUserUtil.searchUsers("hy-zyd",
	// null));
	// String json =js.toString();
	// System.out.println(json);
	// } catch (Exception e) {
	// e.printStackTrace();
	// }
	// }

}
